package com.af.security.auth.util.handler;

import com.af.security.auth.login.service.AfUserDetailsService;
import com.af.security.auth.phone.PhoneAuthenticationToken;
import com.af.security.auth.phone.PhoneUserDetails;
import com.af.security.auth.util.AfAuthenticationUtils;
import com.af.security.auth.user.detail.AfUserDetails;
import com.af.security.jwt.token.JwtTokenService;
import com.af.service.AfRedirectService;
import com.af.system.api.result.AfResultUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.ldap.userdetails.LdapUserDetailsImpl;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author : zhenyun.su
 * @Common : 登录成功后, 自定义返回值及其他操作
 * 1. 自定义返回值， 可以是默认Result格式Json数据; 也可以指定页面,甚至按角色来返回不同Json数据或页面
 * 2. 统一认证数据， 现将认证数据放到session中, 为前端页面存放主体数据(用户信息， 菜单信息，权限信息等)
 * @since : 2020/09/21
 */

@Component
public class AfAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
    private static final Logger logger = LoggerFactory.getLogger(AfAuthenticationSuccessHandler.class);
    private AfRedirectService redirectService;
    private AfUserDetailsService userDetailsService;
    private JwtTokenService jwtTokenService;

    public AfAuthenticationSuccessHandler(AfRedirectService redirectService, AfUserDetailsService userDetailsService, JwtTokenService jwtTokenService) {
        this.redirectService = redirectService;
        this.userDetailsService = userDetailsService;
        this.jwtTokenService = jwtTokenService;
    }

    /**
     * @comment : 登录成功后，返回Result的Json数据
     */
    @Override
    public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
        Object principal = authentication.getPrincipal();
        String password = AfAuthenticationUtils.obtainPassword(httpServletRequest);

        if (principal instanceof AfUserDetails) {
            logger.debug("af, Dao Authentication Success, principal: {}", principal);
        } else if (principal instanceof LdapUserDetailsImpl) {
            AfUserDetails userDetails = userDetailsService.ldapLoginSuccessAndUpdateAccount(authentication.getName(), password, ((LdapUserDetailsImpl) principal).getDn());
            UsernamePasswordAuthenticationToken authData = new UsernamePasswordAuthenticationToken(userDetails, "", userDetails.getAuthorities());
            authData.setDetails(authentication.getDetails());
            SecurityContextHolder.getContext().setAuthentication(authData);
            logger.debug("af, Ldap Authentication Success, update principal and save to session: {}", principal);
        } else if (principal instanceof PhoneUserDetails){
            AfUserDetails userDetails = userDetailsService.loadUserByPhone(((PhoneUserDetails) principal).getPhone());
            PhoneAuthenticationToken authData = new PhoneAuthenticationToken(userDetails, userDetails.getAuthorities());
            authData.setDetails(authentication.getDetails());

            SecurityContextHolder.getContext().setAuthentication(authData);
            logger.debug("af, Ldap Authentication Success, update principal and save to session: {}", principal);
            AfAuthenticationUtils.removeUserDetails(httpServletRequest);
        }
        AfAuthenticationUtils.addPrincipal(httpServletRequest, SecurityContextHolder.getContext().getAuthentication().getPrincipal());

        // 创建jwt token
        String jwtToken = jwtTokenService.createToken(authentication);
        redirectService.redirectJson(httpServletResponse, AfResultUtils.success(jwtToken,"login success"));
    }
}
